package com.kingsoft.dc.khaos.module.spark.util

import java.io.InputStream

import com.kingsoft.dc.khaos.util.Logging
import com.ksyun.auth.client.AuthenticationHelper
import org.apache.http.HttpEntity
import org.apache.http.client.config.RequestConfig
import org.apache.http.client.methods.{CloseableHttpResponse, HttpGet, HttpPost}
import org.apache.http.entity.StringEntity
import org.apache.http.impl.client.{CloseableHttpClient, DefaultHttpClient, HttpClients}

import scala.io.Source


/**
  * HTTP请求工具类
  *
  *
  */
object HttpUtils extends Logging {

  /** 每个多久检查，单位秒 */
  val checkPeriod = 10

  /** 检查次数 */
  val checkTimes = 6

  /** AK */
  private val ak = "kdts-integration"

  /** SK */
  private val sk = "72b73594-7ea3-40f4-9d9e-2e7215066d2e"

  /** authServerUrl */
  //  private val authServerUrl = "http://10.69.56.153:8080/auth"


  /**
    * POST方式获取元数据
    *
    * @param url
    * @param jsonObj json对象
    * @return
    */
  def getMetaByPostWithRight(url: String, authServerUrl: String, jsonstr: String) = {

    var content = ""
    val httpClient = HttpClients.createDefault()
    val requestConfig = RequestConfig.custom()
      .setConnectTimeout(60000)
      .setConnectionRequestTimeout(10000)
      .setSocketTimeout(60000).build()

    logInfo(s"开始组件认证......")
    //第一步：初始化拦截器，拦截Header的拦截器，用于验证后台APP发送的请求
    val headerInterceptor = AuthenticationHelper.getHeaderInterceptor(ak, sk, authServerUrl);
    //第二步：使用auth-client提供的工具类生成动态token
    val token = AuthenticationHelper.getToken()
    try {
      val post: HttpPost = new HttpPost(url)
      post.setConfig(requestConfig)
      //设置提交参数为application/json
      post.addHeader("Content-Type", "application/json")
      post.addHeader("X-AUTH-APP", "kdts-integration")
      post.addHeader("X-AUTH-TOKEN", token)
      post.setEntity(new StringEntity(jsonstr))
      content = checkMeta(httpClient, post, 0)
      content
    } catch {
      case e: Exception =>
        e.printStackTrace()
        logError("HTTP请求接口失败！！！",new Exception(s" 失败信息：${e.getMessage} 失败原因：${e.getCause}"))
        ""
    } finally {
      try {
        if (httpClient != null)
          httpClient.close()
      } catch {
        case e: Exception => println(e.getMessage)
      }
    }
  }

  /**
    * POST方式获取元数据
    *
    * @param url
    * @param jsonObj json对象
    * @return
    */

  def getMetaByPost(url: String, jsonstr: String):String = {

    var content = ""
    val httpClient = HttpClients.createDefault()
    val requestConfig = RequestConfig.custom()
      .setConnectTimeout(60000)
      .setConnectionRequestTimeout(10000)
      .setSocketTimeout(60000).build()

    try {
      val post: HttpPost = new HttpPost(url)
      post.setConfig(requestConfig)
      //设置提交参数为application/json
      post.addHeader("Content-Type", "application/json")
      post.setEntity(new StringEntity(jsonstr))
      content = checkMeta(httpClient, post, 0)
      content
    } catch {
      case e: Exception => e.getMessage
    } finally {
      try {
        if (httpClient != null)
          httpClient.close()
      } catch {
        case e: Exception => println(e.getMessage)
      }
    }
  }

  /**
    * 检查元数据结果
    *
    * @param httpClient
    * @param post
    * @param tryCount
    * @return
    */
  private[this] def checkMeta(httpClient: CloseableHttpClient, post: HttpPost, tryCount: Int): String = {
    var content = ""
    var httpResponse: CloseableHttpResponse = null
    try {
      if (tryCount <= checkTimes - 1) { //如果统计次数小于设置次数
        //执行请求
        httpResponse = httpClient.execute(post)

        if (httpResponse != null && httpResponse.getStatusLine.getStatusCode == 200) {
          //返回结果
          val entity: HttpEntity = httpResponse.getEntity
          val inputStream = entity.getContent()
          content = Source.fromInputStream(inputStream).getLines.mkString
        } else if (httpResponse != null && httpResponse.getStatusLine.getStatusCode == 500) {
          logWarning("http response status code is 500.")
          logInfo(s"waiting $checkPeriod second......")
          Thread.sleep(checkPeriod)
          val count = tryCount + 1
          //重试请求
          logWarning(s"retry check meta $tryCount/$checkTimes.")
          checkMeta(httpClient, post, count)

        } else {
          throw new Exception(s"status code is ${httpResponse.getStatusLine.getStatusCode} and content=${content} , check meta failed.")
        }
      } else {
        throw new Exception(s"status code is ${httpResponse.getStatusLine.getStatusCode} and content=${content} , check meta failed.")
      }
      content
    } catch {
      case e: Exception => e.getMessage
    } finally {
      try {
        if (httpResponse != null)
          httpResponse.close()
      } catch {
        case e: Exception => e.getMessage
      }
    }
  }

  /**
    * 返回请求的内容
    *
    * @param url 请求URL
    * @return 返回值
    */
  def getMetaByGet(url: String) = {
    var httpClient: DefaultHttpClient = null
    var inputStream: InputStream = null
    var content = ""
    try {
      httpClient = new DefaultHttpClient()
      val httpResponse = httpClient.execute(new HttpGet(url))
      val entity = httpResponse.getEntity()
      if (entity != null) {
        inputStream = entity.getContent()
        content = Source.fromInputStream(inputStream).getLines.mkString
      }
      content
    } catch {
      case e: Exception => e.getMessage
    } finally {
      if (inputStream != null) inputStream.close
      if (httpClient != null) httpClient.getConnectionManager().shutdown()
      content
    }
  }

  /**
    * 返回请求的内容
    *
    * @param url 请求URL
    * @return 返回值
    */
  def getWithRight(url: String, authServerUrl: String): String = {
    logInfo("getWithRight:" + url)
    var httpClient: DefaultHttpClient = null
    var inputStream: InputStream = null
    var content = ""
    try {
      httpClient = new DefaultHttpClient()
      //第一步：初始化拦截器，拦截Header的拦截器，用于验证后台APP发送的请求
      val headerInterceptor = AuthenticationHelper.getHeaderInterceptor(ak, sk, authServerUrl);

      //第二步：使用auth-client提供的工具类生成动态token
      val token = AuthenticationHelper.getToken()
      print(token)
      try {
        val get: HttpGet = new HttpGet(url)
        //设置提交参数为application/json
        get.addHeader("Content-Type", "application/json")
        get.addHeader("X-AUTH-APP", "kdts-integration")
        get.addHeader("X-AUTH-TOKEN", token)
        val httpResponse = httpClient.execute(get)
        val entity = httpResponse.getEntity()
        if (entity != null) {
          inputStream = entity.getContent()
          content = Source.fromInputStream(inputStream).getLines.mkString
        }
        content
      } catch {
        case e: Exception => e.getMessage
      } finally {
        if (inputStream != null) inputStream.close
        if (httpClient != null) httpClient.getConnectionManager().shutdown()
        content
      }
    }
  }

  def main(args: Array[String]): Unit = {
    //hive数据源测试
//    val result = getMetaByPost("http://dm.bigdata.yun.ksyun.com/dmgMdQuery/ds/source/physicalInfo/", "{\"env\":\"test\",\"projectId\":77,\"dsId\":65,\"dbName\":\"spark_test1\",\"tblName\":\"source_test3\",\"privilege\":\"read\"}")
    //mpp数据源测试
    //val result = getMetaByPost("http://dm.bigdata.yun.ksyun.com/dmgMdQuery/ds/source/physicalInfo/","{\"env\":\"test\",\"projectId\":77,\"dsId\":73,\"dbName\":\"mpp_test1\",\"tblName\":\"mpp_table\",\"privilege\":\"read\"}")
    //cos数据源测试
    //val result = getMetaByPost("http://dm.bigdata.yun.ksyun.com/dmgMdQuery/ds/source/physicalInfo/","{\"env\":\"test\",\"projectId\":77,\"dsId\":65,\"dbName\":\"spark_test1\",\"tblName\":\"source_test3\",\"privilege\":\"read\"}")


    val result = getWithRight("http://10.69.57.65:3000/mock/172/privilege/api/aksk/1", "http://10.69.65.242:8080/auth")
    print(result)
  }
}
